package com.bss.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.faces.model.DataModel;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;

import com.andy.basics.Constants;
import com.andy.basics.Service;
import com.bss.dao.AdmissionDao;
import com.bss.dao.BedDao;
import com.bss.dao.PatientDao;
import com.bss.dao.RoomDao;
import com.bss.model.Admission;
import com.bss.model.BedBooking;
import com.bss.model.Building;
import com.bss.model.Patient;
import com.bss.model.Room;
import com.bss.model.RoomBooking;
import com.bss.model.RoomOccupancy;
import com.bss.service.AdmissionService;
import com.bss.service.IdGenerationService;
import com.bss.service.RoomOccupancyService;
import com.bss.service.RoomService;

@Controller
@Scope("request")
public class RoomOccupancyController extends com.andy.basics.Controller<RoomOccupancy> {

	private static final String CLASS = RoomOccupancyController.class.getName();

	private static final Logger TRACE = Logger.getLogger(Constants.TRACE_KEY + RoomOccupancyController.CLASS);

	private static final Logger DEBUG = Logger.getLogger(Constants.DEBUG_KEY + RoomOccupancyController.CLASS);

	private static final Logger AUDIT = Logger.getLogger(Constants.AUDIT_KEY + RoomOccupancyController.CLASS);

	private static final Logger ERROR = Logger.getLogger(Constants.ERROR_KEY + RoomOccupancyController.CLASS);

	@Autowired
	private RoomOccupancyService roomOccupancyService;

	@Autowired
	private RoomService roomService;

	@Autowired
	private IdGenerationService idGenerationService;

	@Autowired
	protected AdmissionService admissionService;

	@Autowired
	private AdmissionDao admissionDao;

	@Autowired
	private RoomDao roomDao;

	@Autowired
	private BedDao bedDao;

	@Autowired
	private PatientDao patientDao;

	private Integer selectedPatientId = null;

	private boolean forCurrent;

	private List<Building> buildings = null;

	public RoomOccupancyController() {
	}

	@Override
	public Service<RoomOccupancy> getService() {
		return this.roomOccupancyService;
	}

	@Override
	public RoomOccupancy create() {
		return new RoomOccupancy();
	}

	public List<Building> getBuildings() {
		if (this.buildings == null) {
			this.buildings = this.roomOccupancyService.getBuildings();
		}
		return this.buildings;
	}

	public void setSelectedPatientId(final Integer selectedPatientId) {
		this.selectedPatientId = selectedPatientId;
	}

	public Integer getSelectedPatientId() {
		return this.selectedPatientId;
	}

	public void allocateRoom() {
		this.roomOccupancyService.allocateRoom(this.getDate());
	}

	public void allocateBed() {
		this.roomOccupancyService.allocateBed(this.getDate());
	}

	public void deallocateBed() {
		this.roomOccupancyService.deallocateBed(this.getDate());
	}

	public void deallocateRoom() {
		this.roomOccupancyService.deallocateRoom(this.getDate());
	}

	public RoomBooking getRoomBooking() {
		return this.roomOccupancyService.getRoomBooking();
	}

	public BedBooking getBedBooking() {
		return this.roomOccupancyService.getBedBooking();
	}

	public void selectRoom() {
		System.out.println("start select room");
		this.roomOccupancyService.getRoomBooking().setRoom(this.roomDao.findById(this.getRoomBooking().getRoom().getId()));
		this.roomOccupancyService.getRoomBooking().setRate(this.roomOccupancyService.getRoomBooking().getRoom().getRate());
		System.out.println("finish select room");
	}

	public void selectBed() {
		this.roomOccupancyService.getBedBooking().setBed(this.bedDao.findById(this.getBedBooking().getBed().getId()));
		this.roomOccupancyService.getBedBooking().setRate(this.roomOccupancyService.getBedBooking().getBed().getRoom().getRate());
	}

	@Override
	@Transactional
	public String select() {
		Admission admission = (Admission) this.idGenerationService.getData().getRowData();

		admission = this.admissionDao.findById(admission.getId());
		this.admissionService.populateAdmission(admission);
		this.roomOccupancyService.getRoomBooking().setAdmission(admission);
		this.roomOccupancyService.getBedBooking().setAdmission(admission);
		return null;
	}

	public DataModel admissions(final Object patientName) {
		if (patientName == null) {
			return null;
		}
		return this.idGenerationService.getActiveAdmissionData(patientName.toString());
	}

	public Patient getPatient() {
		return this.selectedPatientId == null ? null : this.patientDao.findById(this.selectedPatientId);
	}

	public void cancelBooking() {
		this.selectedPatientId = null;
		this.roomOccupancyService.setRoomBooking(null);
		this.roomOccupancyService.setBedBooking(null);
	}

	public boolean isForCurrentAdmission() {
		String forCurrentAdmission = this.getHttpUtil().getRequestParameter("forCurrentAdmission");
		return forCurrentAdmission == null ? false : "true".equals(forCurrentAdmission);
	}

	public List<Room> findRooms(final Building building, final int floor) {
		List<Room> rooms = new ArrayList<Room>();
		for (Building buildingVar : this.getBuildings()) {
			if (buildingVar.getId().equals(building.getId())) {
				for (Room room : buildingVar.getRooms()) {
					if (!room.isDormitory() && room.getFloor().equals(floor)) {
						rooms.add(room);
					}
				}
			}
		}
		return rooms;
	}

	public List<Room> findDormitories(final Building building, final int floor) {
		List<Room> rooms = new ArrayList<Room>();
		for (Building buildingVar : this.getBuildings()) {
			if (buildingVar.getId().equals(building.getId())) {
				for (Room room : buildingVar.getRooms()) {
					if (room.isDormitory() && room.getFloor().equals(floor)) {
						rooms.add(room);
					}
				}
			}
		}
		return rooms;
	}

	public List<Room> findRooms() {
		List<Room> rooms = new ArrayList<Room>();
		for (Building buildingVar : this.getBuildings()) {
			for (Room room : buildingVar.getRooms()) {
				rooms.add(room);
			}
		}
		return rooms;
	}

	public List<Room> findRooms(final String condition) throws Exception {

		try {
			RoomOccupancyController.TRACE.trace("Condition: " + condition);

			return this.roomService.findRooms(this.findRooms(), condition);

		} catch (Exception e) {
			RoomOccupancyController.ERROR.error("Exception in findRooms(): " + e.getMessage(), e);
		}
		return null;
	}

	public void setForCurrent(boolean forCurrent) {
		this.forCurrent = forCurrent;
	}

	public boolean isForCurrent() {
		return this.forCurrent;
	}

	@Override
	public Date getDate() {
		return new Date();
	}

}
